#pragma once


#include "Watcher.h"
#include <atomic>
#include <mutex>
#include <thread>
#include <vector>
#include <memory>
#include <functional>

struct event_base;


typedef std::function<void()> void_0_arg_fun;

class LoopService
{
    LoopService(const LoopService&) = delete;
    void operator=(const LoopService&) = delete;
public:
	LoopService();

	LoopService(struct event_base* base);

	~LoopService();

	struct event_base* event_base() {
		return evbase_;
	}

	bool is_in_loop_thread() const {
		return tid_ == std::this_thread::get_id();
	}

	bool is_running() const {
		return runing_.load() == true;
	}

    // @brief Reinitialize some data fields after a fork
    void after_fork();

	// @brief Run the IO Event driving loop forever
	// @note It must be called in the IO Event thread
	void run();

	// @brief Stop the event loop
	void stop();

	void dispatch(const void_0_arg_fun& handler);

	void post(const void_0_arg_fun& handler);

private:
	void _init();
	void _init_notify_pipe_watcher();
	void _stop_in_loop();
	void _do_pending_functors();
	size_t _get_pending_queue_size(){
		return pending_functors_.size();
	}
	bool _is_pending_queue_empty(){
		return pending_functors_.empty();
	}
private:
	struct event_base*				evbase_;
	bool							create_evbase_myself_;
	std::thread::id					tid_;
	std::atomic<bool>				runing_;

	std::shared_ptr<PipeEventWatcher> watcher_;

	std::mutex						mutex_;
	std::vector<void_0_arg_fun>		pending_functors_;
	std::atomic<bool>				notified_;
	std::atomic<int>				pending_functor_count_;
};





